package com.company.project.wechat.officialAccounts.service.impl;

import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.nacos.api.config.annotation.NacosValue;
import com.company.project.wechat.commom.WxUtils;
import com.company.project.wechat.officialAccounts.emun.WxMessageType;
import com.company.project.wechat.officialAccounts.entity.*;
import com.company.project.wechat.officialAccounts.service.WxOfficialAccountsService;
import com.company.project.wechat.commom.HttpUtils;
import com.company.project.wechat.commom.ReplyMessageUtil;
import com.company.project.wechat.commom.WxOfficialAccountsUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.util.HashMap;
import java.util.Map;


/**
 * 微信开放接口相关
 * @author ZYF
 * @date 2021/5/18 11:03
 */
@Service
@Slf4j
public class WxOfficialAccountsServiceImpl implements WxOfficialAccountsService {

    //    获取access_token填写client_credential
    private final String GrantType = "client_credential";

    //    第三方用户唯一凭证
    @NacosValue(value = "${wx.appId:1}",autoRefreshed = true)
    private String AppId ;

    //    第三方用户唯一凭证密钥，即AppSecret
    @NacosValue(value = "${wx.appSecret:1}",autoRefreshed = true)
    private String AppSecret;

    //小程序APPid
    @NacosValue(value = "${wxpay.appid:1}",autoRefreshed = true)
    private String MinAppid;

    /**
     * Token可由开发者可以任意填写，用作生成签名（该Token会和接口URL中包含的Token进行比对，从而验证安全性）
     * 比如这里我将Token设置为gacl
     */
    @NacosValue(value = "${wx.token:1}",autoRefreshed = true)
    private String token;

    @Autowired
    HttpUtils httpUtils;

    @Autowired
     WxUtils wxUtils;

    /**
     * 微信签名校验（微信接入）
     * @param signature 微信加密签名
     * @param timestamp 时间戳
     * @param nonce 随机数
     * @param echostr 随机字符串
     * @return
     */
    @Override
    public String getValidateCode(String signature, String timestamp, String nonce, String echostr) {
        log.info("接收到来自微信服务器的认证消息：[{},{},{},{}]",signature,timestamp,nonce,echostr);
        if(!StringUtils.isEmpty(signature) || !StringUtils.isEmpty(timestamp) ||
                !StringUtils.isEmpty(nonce) || !StringUtils.isEmpty(echostr)){
            //排序
            WxOfficialAccountsUtils utils = new WxOfficialAccountsUtils();
            String sortString = utils.sort(token, timestamp, nonce);
            //加密
            String mySignature = utils.sha1(sortString);
            //校验签名
            if (mySignature != null && mySignature != "" && mySignature.equals(signature)) {
                log.info("签名校验通过。");
                //如果检验成功输出echostr，微信服务器接收到此输出，才会确认检验完成。
                return echostr;
            } else {
                log.error("签名校验失败.");
                return "-1";
            }
        }else{
            log.error("请求不是来自微信！！");
            return "-1";
        }
    }
    @Override
    public void acceptMessage(HttpServletRequest request, HttpServletResponse response) throws Exception {
        // 处理接收消息
        ServletInputStream in = request.getInputStream();
        // 将流转换为字符串
        StringBuilder xmlMsg = new StringBuilder();
        byte[] b = new byte[4096];
        for (int n; (n = in.read(b)) != -1;) {
            xmlMsg.append(new String(b, 0, n, "UTF-8"));
        }
        request.setCharacterEncoding("UTF-8");
        response.setCharacterEncoding("UTF-8");
        if (xmlMsg.toString().indexOf("<Encrypt>") > -1) {
            log.info("收到加密消息:" + xmlMsg.toString());
        }
        // 将XML转换为Map
        Map map = wxUtils.transferXmlToMap(xmlMsg.toString());
        MessageData messageData = JSON.parseObject(JSON.toJSONString(map), MessageData.class);
        String serviceid = messageData.getToUserName();// 发送人，为用户的openid
        String openid = messageData.getFromUserName();// 接收人，为公众号的id
        String message = null;

        HashMap<String,String> messgaeMap = new HashMap<>();
        log.info("MsgType:" + messageData.getMsgType().toUpperCase());
        switch (WxMessageType.valueOf(messageData.getMsgType().toUpperCase())) {
            case EVENT:
                messgaeMap = EVENTMessgae(messageData, openid, serviceid);
                message =  messgaeMap.get("message");
                break;
            case IMAGE:
//                message = ReplyMessageUtil.initTextMessage(openid, serviceid, "感谢您发送的图片");
                break;
            case LINK:
                //message = ReplyMessageUtil.initTextMessage(openid, serviceid, "您发的链接" + messageData.getUrl() + "我们已经收到");
                break;
            case LOCATION:
                //message = ReplyMessageUtil.initTextMessage(openid, serviceid, "您发的地理位置" + messageData.getLabel() + "我们已经收到");
                break;
            case SHORTVIDEO:
                //message = ReplyMessageUtil.initVideoMessage(openid, serviceid, messageData.getMediaId());
                break;
            case TEXT:
                //关键字自动回复
//			ReplySearch params = new ReplySearch();
//			params.setKeywords(messageData.getContent());
//			List<Reply> list = replyService.findByParams(params);
//			if(list!=null && list.size()>0) {
//				String content = "";
//				for(Reply reply:list) {
//					content+=reply.getContent();
//				}
//				message = ReplyMessageUtil.initTextMessage(openid, serviceid, content);
//			}
                // message = ReplyMessageUtil.initTextMessage(openid, serviceid,
                // "你说的是:"+messageData.getContent() );
                break;
            case VIDEO:
                //message = ReplyMessageUtil.initVideoMessage(openid, serviceid, messageData.getMediaId());
                break;
            case VOICE:
                //message = ReplyMessageUtil.initVoiceImageMessage(openid, serviceid, messageData.getMediaId(), 2);
                break;
            default:
                //message = ReplyMessageUtil.initTextMessage(openid, serviceid, "未知命令");
                break;
        }

        if (StrUtil.isNotEmpty(message)  ) {
            // 消息回复
            response.getWriter().write(message);
            log.info("回复内容：" + message);
        }

    }

    /**
     * @param messageData
     * @param openid
     * @param serviceid
     * @return
     * @throws Exception
     */
    private HashMap<String,String> EVENTMessgae(MessageData messageData, String openid, String serviceid) throws Exception {
        String message = null;
        String replyMessage = null;
        String start = messageData.getEventKey();
        String content =null;
        // 类型判断
        switch (messageData.getEvent()) {
            case "subscribe":// 关注
                try {
                    if(StrUtil.isNotEmpty(start)){
                        content=  start.replace("qrscene_","");
//                        JSONObject paramsJson = JSONObject.parseObject(content);
//                        log.info(paramsJson.toJSONString());
//                        log.info( paramsJson.getString("goodId"));
                        send(openid,"pages/home/home");
                    }
                    log.info("二维码带的信息：" + content);
                } catch (Exception e) {
                    log.error("错误信息：：：："+e);
                    e.printStackTrace();
                }
                message = ReplyMessageUtil.initTextMessage(openid, serviceid,"测试关注");
                break;
            case "unsubscribe":// 取消关注
                log.info("有客户取消关注你了");
                break;
            case "SCAN":// 关注后的扫码
                // message = SCANMessage(messageData, openid, serviceid);
                try {
                    if(StrUtil.isNotEmpty(start)){
                        content=  start.replace("qrscene_","");
                        send(openid,"pages/home/home");
                    }
                    log.info("二维码带的信息：" + content);
                    log.info("关注后的扫码");
                } catch (Exception e) {
                    log.error("错误信息：：：："+e);
                    e.printStackTrace();
                }
                break;
            case "VIEW":// 自定义菜单,URL跳转
                    log.info("自定义菜单url跳转");
                break;
            case "CLICK":// 自定义菜单,key类型
                // message = CLICKMessage(messageData, openid, serviceid);
                break;
            case "LOCATION":// 位置信息
                // weixinUserService.savePosition(openid, messageData.getLatitude(),
                // messageData.getLongitude(), messageData.getPrecision());
                break;
            default:
                // message = ReplyMessageUtil.initTextMessage(openid, serviceid,
                // "未知请求");
                break;
        }
        HashMap<String,String> map =new HashMap<>();
        map.put("message",message);
        map.put("replyMessage",replyMessage);
        map.put("content",content);
        return map;
    }

    /**
     * 获取AccountToken
     * @return
     */
    @Override
    public String getAccountToken(){
        String url = "https://api.weixin.qq.com/cgi-bin/token?grant_type="+GrantType+"&appid=" + AppId + "&secret=" + AppSecret;
        try{
            JSONObject obj = JSONObject.parseObject(httpUtils.loadGetJson(url,null,"GET"));
            if(StringUtils.isEmpty(obj)){
                log.error("获取AccountToken异常");
                return "获取AccountToken异常";
            }
            String accountToken = obj.getString("access_token");
            return accountToken;
        }catch (Exception ex){
            return "获取AccountToken异常";
        }
    }

    /**
     * 微信公众号 临时二维码
     * 业务可在关注公众号后推送相关的产品信息
     * 文档地址：https://developers.weixin.qq.com/doc/offiaccount/Account_Management/Generating_a_Parametric_QR_Code.html
     * @return
     */
    @Override
    public HashMap<String,String> getTicket()  {
        HashMap<String, String> resultMap = new HashMap();
        try {
            String accountToken = getAccountToken();
            String url = "https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token=" + accountToken;
            log.info(url);
            JSONObject paramsObject = new JSONObject();
            /**
             * 二维码类型，QR_SCENE为临时的整型参数值，QR_STR_SCENE为临时的字符串参数值，QR_LIMIT_SCENE为永久的整型参数值，QR_LIMIT_STR_SCENE为永久的字符串参数值
             */
            paramsObject.put("action_name", "QR_LIMIT_STR_SCENE");
            JSONObject actionInfo = new JSONObject();
            JSONObject scene = new JSONObject();
//          场景值ID（字符串形式的ID），字符串类型，长度限制为1到64
            scene.put("scene_str","二维码要带的参数");
            actionInfo.put("scene", scene);
            paramsObject.put("action_info", actionInfo);
            log.info(paramsObject.toJSONString());
            JSONObject obj = JSONObject.parseObject(httpUtils.loadGetJson(url, paramsObject.toJSONString(), "POST"));
            String ticket = obj.getString("ticket");
            String orCodeUrl = obj.getString("url");
//          ticket 为可以跟微信公众号换取二维码图片的凭证
            resultMap.put("ticket", ticket);
//           orCodeUrl 可以根据这个url自行生成一个二维码
            resultMap.put("orCodeUrl", orCodeUrl);
            return resultMap;
        }catch (Exception ex){
            resultMap.put("二维码创建失败错误","异常信息::::"+ex);
            return resultMap;
        }
    }


    /**
     * 发送小程序卡片
     * @param openId
     * @param pagesPath
     * @return
     */
    public void send(String openId,String pagesPath){
        String accountToken = getAccountToken();
        String url = "https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token="+accountToken;
        log.info(url);
        Miniprogrampage miniprogrampage =new Miniprogrampage();
        miniprogrampage.setTitle("测试");
        miniprogrampage.setAppid(MinAppid);
        UpdateFile updateFile = new UpdateFile();
        updateFile.setFileUrl("C:\\Users\\Administrator\\Desktop\\产品分享.jpg");//图片路径
        updateFile.setType("image");//图片类型
        String mediaId = upload(updateFile);
        if(mediaId.equals("上传临时素材错误")){
            log.error("微信上传临时素材接口错误");
            return ;
        }
        miniprogrampage.setThumb_media_id(mediaId);
        miniprogrampage.setPagepath(pagesPath);

        MinMessage minMessage =new MinMessage();
        minMessage.setMsgtype("miniprogrampage");
        minMessage.setTouser(openId);
        minMessage.setMiniprogrampage(miniprogrampage);
        log.info("发送的参数：：：：：：："+JSON.toJSONString(minMessage));
        JSONObject obj = JSONObject.parseObject(httpUtils.loadGetJson(url,JSON.toJSONString(minMessage),"POST"));
        if(obj.getString("errmsg").equals("ok")){
            log.info("-------------消息推送成功---------------");
        }else{
            log.error("消息推送失败,失败原因：：：：："+obj.toString());
        }
    }

    /**
     * 微信公众号上传临时素材接口
     *
     * 图片（image）: 10M，支持PNG\JPEG\JPG\GIF格式
     *
     * 语音（voice）：2M，播放长度不超过60s，支持AMR\MP3格式
     *
     * 视频（video）：10MB，支持MP4格式
     *
     * 缩略图（thumb）：64KB，支持JPG格式
     * @param updateFile
     */
    @Override
    public String upload(UpdateFile updateFile) {
        try {
            File file = new File(updateFile.getFileUrl());
            String request = null;
            //上传素材
            // 临时素材url
//            String url = "https://api.weixin.qq.com/cgi-bin/media/upload?access_token=" + getAccountToken() + "&type=" + updateFile.getType();
            // 永久素材url
            String url = "https://api.weixin.qq.com/cgi-bin/material/add_material?access_token=" + getAccountToken() + "&type=" + updateFile.getType();
            String result = httpUtils.connectHttpsByPost(url, file);
            result = result.replaceAll("[\\\\]", "");
            log.info("result:" + result);
            JSONObject resultJSON = JSONObject.parseObject(result);
            if (resultJSON != null) {
                if (resultJSON.getString("media_id") != null) {
                    request = resultJSON.getString("media_id");
                    log.info("上传" + updateFile.getType() + "临时素材成功");
                } else {
                    request = "上传临时素材错误";
                    log.error("上传" + updateFile.getType() + "临时素材失败");
                }
            }
            return request;
        } catch (Exception ex) {
            log.error(ex.toString());
            return "错误异常"+ex;
        }
    }

    /**
     * 微信公众号自定义菜单
     * @param menuJson
     * @return
     */
    @Override
    public Boolean setWxMenu(String menuJson) {
        String requestUrl = "https://api.weixin.qq.com/cgi-bin/menu/create?access_token="+getAccountToken();
        JSONObject obj = JSONObject.parseObject(httpUtils.loadGetJson(requestUrl, menuJson, "POST"));
       log.error("setWxMenu errcode:" + obj.getString("errcode"));
        if (!obj.getString("errcode").equals(0)) {
            log.info("创建菜单成功");
            return false;
        }
        return true;
    }



}
